package ru.xeden.web.request.internal;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import ru.xeden.core.common.Utils;
import ru.xeden.web.request.IRequest;


public class RequestImpl
    implements IRequest
{
    static final String REQUESTED_WITH_HEADER = "X-Requested-With";
    static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    private final HttpServletRequest request;
    private final String requestEncoding;
    private boolean encodingSet;
    private String servletPath;

    //    Session session;
    public RequestImpl(HttpServletRequest request, String requestEncoding/*,
                                                                         TapestrySessionFactory sessionFactory*/)
    {
        this.request = request;
        this.requestEncoding = requestEncoding;
        //        this.sessionFactory = sessionFactory;
    }

    public String getRequestURI()
    {
        return this.request.getRequestURI();
    }

    public List<String> getParameterNames()
    {
        setupEncoding();
        return Utils.toList(request.getParameterNames());
    }

    public List<String> getHeaderNames()
    {
        return Utils.toList(request.getHeaderNames());
    }

    public String getParameter(String name)
    {
        setupEncoding();
        return request.getParameter(name);
    }

    public String [] getParameters(String name)
    {
        setupEncoding();
        return request.getParameterValues(name);
    }

    public String getHeader(String name)
    {
        return request.getHeader(name);
    }

    public String getPath()
    {
        String pathInfo = request.getPathInfo();
        if (pathInfo == null)
        {
            return request.getServletPath();
        }
        return pathInfo.length() == 0 ? "/" : pathInfo;
    }

    public String getContextPath()
    {
        return request.getContextPath();
    }

    public Locale getLocale()
    {
        return request.getLocale();
    }

    public long getDateHeader(String name)
    {
        return request.getDateHeader(name);
    }

    private void setupEncoding()
    {
        if (encodingSet)
            return;
        try
        {
            request.setCharacterEncoding(requestEncoding);
        }
        catch (UnsupportedEncodingException ex)
        {
            throw new RuntimeException(ex);
        }
        encodingSet = true;
    }

    public boolean isXHR()
    {
        return XML_HTTP_REQUEST.equals(request.getHeader(REQUESTED_WITH_HEADER));
    }

    public boolean isSecure()
    {
        return request.isSecure();
    }

    public boolean isRequestedSessionIdValid()
    {
        return request.isRequestedSessionIdValid();
    }

    public Object getAttribute(String name)
    {
        return request.getAttribute(name);
    }

    public void setAttribute(String name, Object value)
    {
        request.setAttribute(name, value);
    }

    public String getMethod()
    {
        return request.getMethod();
    }

    public String getServerName()
    {
        return request.getServerName();
    }

    public int getLocalPort()
    {
        return request.getLocalPort();
    }

    public int getServerPort()
    {
        return request.getServerPort();
    }

    public String getRemoteHost()
    {
        return request.getRemoteHost();
    }

    public String getServletPath()
    {
        if (servletPath == null)
        {
            synchronized (this)
            {
                if (servletPath == null)
                {
                    servletPath = request.getServletPath();
                }
            }
        }
        return servletPath;
    }
    
    public Map<String, String> getParameterMap()
    {
        Map<String, String> params = new HashMap<String, String>();
        List<String> names = getParameterNames();
        for(String name : names)
        {
            params.put(name, getParameter(name));
        }
        return params;
    }
    
}
